package sk.upjs.ics.fca.bonds.bruteforce;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import sk.upjs.ics.fca.concepts.ClosureType;
import sk.upjs.ics.fca.concepts.Context;

/**
 * Tato trieda riesi generovanie put medzi dvoma kontextami brute force
 * pristupom
 * 
 * @author Patrik Mihalcin
 */
public class BondsFactoryBruteForce {

	private Context c1;
	private Context c2;
	private List<List<Double>> extentsC1;
	private List<List<Double>> intentsC2;
	private List<List<List<Double>>> extentVariations;
	private List<List<List<Double>>> intentVariations;
	private Set<List<List<Double>>> bonds = new HashSet<List<List<Double>>>();

	/**
	 * Konstruktor prijima ako vstupy 2 kontexty, medzi ktorymi vygenerujeme
	 * puta
	 * 
	 * @param c1
	 *            prvy kontext
	 * @param c2
	 *            druhy kontext
	 */
	public BondsFactoryBruteForce(Context c1, Context c2) {
		super();
		this.c1 = c1;
		this.c2 = c2;
		c1.lattice(ClosureType.UP_DOWN);
		c2.lattice(ClosureType.DOWN_UP);
	}

	/**
	 * Generuje mnozinu vsetkych bondov
	 */
	public void generateLatticeOfBonds() {
		extentsC1 = c1.getExtents();
		intentsC2 = c2.getIntents();

		VariationsWithoutRepetition extentGenerator = new VariationsWithoutRepetition(
				extentsC1, c2.getAttributesCount());
		extentGenerator.generate();
		extentVariations = extentGenerator.getAllVariations();

		VariationsWithoutRepetition intentGenerator = new VariationsWithoutRepetition(
				intentsC2, c1.getObjectsCount());
		intentGenerator.generate();
		intentVariations = intentGenerator.getAllVariations();

		for (List<List<Double>> extentVariation : extentVariations) {
			List<List<Double>> transposedVariation = transpose(extentVariation);
			if (intentVariations.contains(transposedVariation)) {
				bonds.add(extentVariation);
			}
		}

		// for (List<List<Double>> intentVariation : intentVariations) {
		// List<List<Double>> transposedVariation = transpose(intentVariation);
		// if (extentVariations.contains(transposedVariation)) {
		//
		// }
		// }
	}

	private List<List<Double>> transpose(List<List<Double>> fuzzySets) {
		List<List<Double>> result = new ArrayList<List<Double>>();

		for (int i = 0; i < fuzzySets.get(0).size(); i++) {
			List<Double> temp = new ArrayList<Double>();
			for (int j = 0; j < fuzzySets.size(); j++) {
				temp.add(fuzzySets.get(j).get(i));
			}
			result.add(temp);
		}

		return result;
	}

	/**
	 * Vrati mnozinu najdenych put
	 * 
	 * @return mnozina najdenych put
	 */
	public Set<List<List<Double>>> getBonds() {
		return bonds;
	}
}
